#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <cstring>
void Usage(char *proc)
{
    std::cout << "/r/nUsage:" << proc << " serverip" << " serverport" << std::endl;
}
// tcpclient serverip serverport
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(-2);
    }
    std::string serverip = argv[1];           // 服务器ip
    uint16_t serverport = std::stoi(argv[2]); // 服务器端口
  
    // 2. 准备数据
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));                     // 初始化
    server.sin_family = AF_INET;                            // ip协议家族
    server.sin_port = htons(serverport);                    // 主机转网络
    inet_pton(AF_INET, serverip.c_str(), &server.sin_addr); // 串转地址，这里sin_addr就可
    // 3.客户端必须绑定，无需显式绑定，第一次connect成功自动绑定，OS随机分配端口
    // 4.连接
    while (true)
    {
        // 上来先看能否连接上，是否需要重连
        int cnt = 5;              // 最多重连5次
        bool isreconnect = false; // 是否正在重连
          // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("make sock fail!");
        exit(-1);
    }
        do
        {
            int n = connect(sockfd, (sockaddr *)&server, sizeof(server)); // 5.收发数据
            if (n < 0)
            {
                // 重新连接
                cnt--;
                isreconnect=true;
                std::cout<<"connect err, isreconnect:"<<isreconnect<<" ,time : "<<cnt;
                sleep(2);//每隔两秒重连
            }
            else{
                break;//连接成功
            }

        } while (cnt&isreconnect);//循环条件：重连状态+重连次数
        if(cnt==0)
        {
            //重连次数用完还没连接成功
            std::cout<<" user offline!!"<<std::endl;
            break;//退出
        }
        //走到这代表连接成功
        std::string line;
            std::cout << "please enter @";
            std::getline(std::cin, line);
            ssize_t n=write(sockfd, line.c_str(), line.size()); // 写
            if(n<0)
            {
                //写入失败
                //break;
            }
            char buffer[4096];
           ssize_t s= read(sockfd,buffer,sizeof(buffer));
           if(s<0)
           {
            //读取失败
            //break;
           }
            else if(s==0)
            {
                //写端关闭
               // break;
            }
            else
            {
                //读取成功
                buffer[s]='\0';
               std:: cout<<buffer<<std::endl;
            }
            close(sockfd);//使用完成关闭套接字
    }
    return 0;
}